package be.castanea.client.util;

import be.castanea.client.CastaneaClient;
import be.castanea.client.model.World;
import com.jme.util.export.binary.BinaryClassLoader;
import com.mw3d.terrain.model.binary.module.TerrainAlphaLayerModule;
import com.mw3d.terrain.model.binary.module.TerrainBaseLayerModule;
import com.mw3d.terrain.model.binary.module.TerrainModelModule;
import com.mw3d.terrain.model.binary.module.TerrainPropertiesBeanModule;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.system.DisplaySystem;
import com.jme.util.export.JMEImporter;
import com.jme.util.export.Savable;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.terrain.util.AbstractHeightMap;
import com.jmex.terrain.util.ImageBasedHeightMap;
import com.mw3d.terrain.model.TerrainAlphaLayer;
import com.mw3d.terrain.model.TerrainBaseLayer;
import com.mw3d.terrain.model.TerrainModel;
import com.mw3d.terrain.model.TerrainPropertiesBean;
import java.util.List;

/**
 * Castanea
 * 2009
 * @author Geert van Leemputten, Steven Rymenans, Bart Van Hooydonck
 */
public class MapLoader {

    public static Node scene;


    static {
        BinaryClassLoader.registerModule(new TerrainModelModule());
        BinaryClassLoader.registerModule(new TerrainPropertiesBeanModule());
        BinaryClassLoader.registerModule(new TerrainBaseLayerModule());
        BinaryClassLoader.registerModule(new TerrainAlphaLayerModule());
    }

    public static void loadMap(String mapName, Node rootNode) {
        String jmeFileName = MapLoader.class.getClassLoader().getResource("resources/zones/" + mapName + ".jme").getFile();
        // Load the terrain configuration file
        String terrainFileName = jmeFileName.replaceAll(".jme", ".terrain");

        // then lets try to load this file.
        JMEImporter im = BinaryImporter.getInstance();
        TerrainModel terrainModel = null;
        try {
            File file = new File(terrainFileName);
            System.out.println(file.getAbsolutePath());
            if (file.exists()) {
                Savable item = im.load(file);
                if (item != null) {
                    terrainModel = (TerrainModel) item;
                }
            }
        } catch (Exception e) {
        }

        File file = null;

        // now after load we will check for any available height map to load
        String pngFileName = jmeFileName.replaceAll(".jme", "-terrain-heightmapimage.png");
        // now lets try to get a file.
        AbstractHeightMap heightMap = null;
        try {
            file = new File(pngFileName);
            if (file != null) {
                heightMap = loadHeightMap(file.getAbsolutePath());
            }
        } catch (Exception e) {
        }

        if (terrainModel != null) {
            if (terrainModel.getProperties() != null) {
                TerrainPropertiesBean bean = terrainModel.getProperties();
                createHeightMapTerrain(heightMap, bean.getSize(), bean.getBlockSize(), new Vector3f(bean.getXScale(), bean.getYScale(), bean.getZScale()), false);
            }
        }

        try {
            File f = new File(jmeFileName);
            scene = (Node) BinaryImporter.getInstance().load(f);
            rootNode.attachChild(scene);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (World.getInstance() != null) {
            rootNode.attachChild(World.getInstance());
        }

        rootNode.updateGeometricState(0.0f, true);
        rootNode.updateRenderState();

        loadLayers(rootNode, terrainModel);
    }

    private static AbstractHeightMap loadHeightMap(String filepath) {
        AbstractHeightMap map = null;
        try {
            File file = new File(filepath);
            BufferedImage bufferedImage = ImageIO.read(file);
            map = new ImageBasedHeightMap(bufferedImage);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }

    private static void createHeightMapTerrain(AbstractHeightMap map, int size, int blockSize, Vector3f scale, boolean clod) {
        World.load(blockSize, size + 1, scale, map.getHeightMap());
    }

    private static void loadLayers(Node rootNode, TerrainModel terrainModel) {
        TerrainBaseLayer layer = terrainModel.getBaseLayer();
        if (World.getInstance() != null) {
            SimpleSplatManager manager = new SimpleSplatManager(World.getInstance(), rootNode);
            if (manager == null) {
                return;
            }
            if (layer != null) {
                try {
                    layer.loadFromJme(DisplaySystem.getDisplaySystem().getRenderer());
                    manager.registerBaseLayer(layer);
                } catch (Exception e) {
                }
            }

            List<TerrainAlphaLayer> alphaLayers = terrainModel.getAlphaLayers();

            for (TerrainAlphaLayer alphaLayer : alphaLayers) {
                alphaLayer.loadFromJme(DisplaySystem.getDisplaySystem().getRenderer());
                manager.registerAlphaLayer(alphaLayer);
            }
        }
    }
}
